/*
	Copyright (C) 2010 2011 Rémi Thebault

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <QDebug>

#include <QByteArray>
#include <QDataStream>
#include <QDrag>
#include <QMimeData>
#include <QDragEnterEvent>
#include <QDragLeaveEvent>
#include <QDragMoveEvent>
#include <QPaintEvent>
#include <QPixmap>
#include <QLabel>
#include <QPainter>

#include "tasktreemodel.h"
#include "tasktreecolumnselectdialog.h"
#include "procycle.h"


const QString COL_MIMETYPE = "application/x-procycle-column";


TaskTreeColumnSelectDialog::TaskTreeColumnSelectDialog(ProCycle *parent)
:	QDialog(parent)
,	PCChild(parent)
,	m_model(parent->taskTreeModel())
{
	ui.setupUi(this);

	m_avails = new ColListView(this);
	m_currs = new ColListView(this);


	QList<PC::Task::Data> currents = m_model->columns();
	m_currs->setModel(new ColViewModel(m_app, currents));

	QList<PC::Task::Data> avails;
	for (int i=0; i<PC::Task::DATA_COUNT; i++) {
		if (!m_model->hasColumn(PC::Task::Data(i))) {
			avails.append(PC::Task::Data(i));
		}
	}
	m_avails->setModel(new ColViewModel(m_app, avails));

	ui.availVLayout->addWidget(m_avails);
	ui.currVLayout->addWidget(m_currs);
}

TaskTreeColumnSelectDialog::~TaskTreeColumnSelectDialog()
{
}


QList<PC::Task::Data> TaskTreeColumnSelectDialog::columns() {
	QList<PC::Task::Data> cols;
	ColViewModel* cvm = static_cast<ColViewModel*>(m_currs->model());
	for (int r=0; r<cvm->rowCount(); r++) {
		cols.append(cvm->col(r));
	}
	return cols;
}



QVariant ColViewModel::data(const QModelIndex &index, int role) const {
	if(!index.isValid()) {
		return QVariant();
	}
	if (role == Qt::DisplayRole) {
		PC::Task::Data td = PC::Task::Data(index.internalId());
		return QVariant(m_app->taskTreeHeaderColName(td));
	}
	return QVariant();
}

ColListView::ColListView(QWidget *parent)
:	QListView(parent)
,	m_currInsertRow(-1)
{
	setAcceptDrops(true);
	setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
}

void ColListView::dragEnterEvent(QDragEnterEvent *event) {
	if (event->mimeData()->hasFormat(COL_MIMETYPE)) {
		event->acceptProposedAction();
	} else {
		event->ignore();
	}
}


void ColListView::dragLeaveEvent(QDragLeaveEvent* /*event*/) {
	m_currInsertRow = -1;
	viewport()->update();
}


void ColListView::dragMoveEvent(QDragMoveEvent *event) {
	if (event->mimeData()->hasFormat(COL_MIMETYPE)) {

		QModelIndex lastIndex = model()->index(model()->rowCount()-1, 0);
		QRect lastRect = visualRect(lastIndex);
		if (event->pos().y() > lastRect.bottom()) {
			m_currInsertRow = model()->rowCount();
		}
		else {
			m_currInsertRow = indexAt(event->pos()).row();
		}

		viewport()->update();

		event->acceptProposedAction();

	} else {
		event->ignore();
	}
}


void ColListView::dropEvent(QDropEvent *event) {

	if (event->mimeData()->hasFormat(COL_MIMETYPE)) {

		m_currInsertRow = -1;

		QByteArray itemData = event->mimeData()->data(COL_MIMETYPE);
		QDataStream dataStream(&itemData, QIODevice::ReadOnly);

		int id;
		dataStream >> id;

		int row;
		QModelIndex lastIndex = model()->index(model()->rowCount()-1, 0);
		QRect lastRect = visualRect(lastIndex);
		if (event->pos().y() > lastRect.bottom()) {
			row = model()->rowCount();
		}
		else {
			row = indexAt(event->pos()).row();
		}
		static_cast<ColViewModel*>(model())->insertRow(row, QVariant(id));

		event->acceptProposedAction();

	} else {
		event->ignore();
	}

}


void ColListView::mouseMoveEvent(QMouseEvent *event) {

	if (!(event->buttons() & Qt::LeftButton)) {
		return;
	}
	if ((event->pos() - m_dragStartPosition).manhattanLength()
			< QApplication::startDragDistance()) {
		return;
	}

	QModelIndex index = indexAt(event->pos());
	QLabel l;

	QRect r = visualRect(index);

	l.setText(index.data().toString());
	l.adjustSize();

	QPixmap pm (l.width(), l.height());
	l.render(&pm);

	QByteArray itemData;
	QDataStream dataStream(&itemData, QIODevice::WriteOnly);
	int id = index.internalId();
	dataStream << id;

	QMimeData *mimeData = new QMimeData;
	mimeData->setData(COL_MIMETYPE, itemData);

	QDrag *drag = new QDrag(this);
	drag->setMimeData(mimeData);
	drag->setPixmap(pm);
	drag->setHotSpot(m_dragStartPosition - r.topLeft());

	int row = index.row();
	static_cast<ColViewModel*>(model())->removeRow(row);

	if (drag->exec(Qt::MoveAction) != Qt::MoveAction) {
		static_cast<ColViewModel*>(model())->insertRow(row, QVariant(id));
	}
}


void ColListView::paintEvent(QPaintEvent *e) {
	QListView::paintEvent(e);
	if (m_currInsertRow >= 0) {
		int y;
		QRect r;
		if (m_currInsertRow >= model()->rowCount()) {
			QModelIndex lastIndex = model()->index(model()->rowCount()-1, 0);
			r = visualRect(lastIndex);
			y = r.bottom();
		}
		else {
			QModelIndex index = model()->index(m_currInsertRow, 0);
			r = visualRect(index);
			y = r.top();
		}

		QPainter painter(viewport());
		QPoint p1 (r.left()+2, y);
		QPoint p2 (r.right()-2, y);
		QPen pen (Qt::black);
		pen.setWidth(2);
		painter.setPen(pen);
		painter.drawLine(p1, p2);
	}
}

